#ifndef DSPSIMULATOR_INSTRUCTION_H
#define DSPSIMULATOR_INSTRUCTION_H

#include <string>
#include <memory>
#include <utility>
#include "simulator/targetMachine/targetMachine.h"
#include "simulator/llvmJit/llvmJit.h"
#include "simulator/type/type.h"
#include "simulator/instruction/executePhase.h"
#include "simulator/instruction/instInfo.h"

class Instruction {
protected:
    std::string m_name;  // 指令名
    u64 m_address;       // 指令所在的内存地址
    u64 m_baseCycle;  //  当前指令执行的起始时钟周期
    u64 m_delay; // 延时大小
public:

    /**
     * @param name 指令名
     * @param address 指令地址
     * @param baseCycle 当前指令执行E1阶段的时钟周期
     * @param delay 延时大小
     */
    explicit Instruction(const std::string &name, u64 address, u64 baseCycle, u64 delay) :
            m_name(name), m_address(address), m_baseCycle(baseCycle), m_delay(delay) {};

    virtual ~Instruction() = default;

    Instruction(const Instruction &instruction) = default;

    /**
     * 获取指令所在的内存地址
     * @return 指令所在的内存地址
     */
    u64 getInstructionAddress() const { return m_address; }

    /**
     * 获取指令的名称
     * @return 指令名称
     */
    std::string getName() const { return m_name; }

    /**
     * 获取指令执行的起始时钟周期
     * @return 指令执行的起始时钟周期
     */
    u64 getBaseCycle() const { return m_baseCycle; }

    /**
     * 判断当前指令是否为延时指令
     * @return 如果当前指令是延时指令，返回true，否则返回false
     */
    bool isDelayInstruction() const { return m_delay != 0; }

    /**
     * 获取指令的延时
     * @return 指令的延时
     */
    u64 getDelay() const { return m_delay; }


    /**
     * 根据指令数据解码指令，并返回新的指令对象，该指令对象表示解码完成的指令
     * @param instInfo 指令数据
     * @param baseCycle 指令E1阶段的时钟周期
     * @return
     */
    virtual std::shared_ptr<Instruction> decode(std::shared_ptr<InstInfo> instInfo, u64 baseCycle) = 0;

    /**
     * 修改指令的起始时钟周期
     * @param baseCycle  指令的起始时钟周期
     */
    void updateBaseCycle(u64 baseCycle) {
        m_baseCycle = baseCycle;
    }

    virtual std::string toString() = 0;
};

#endif //DSPSIMULATOR_INSTRUCTION_H
